package com.pxml2pdf.pdf;

import java.util.ArrayList;
import java.util.List;

import com.itextpdf.text.PageSize;
import com.pxml2pdf.pdf.Node.BaseNode;
import com.pxml2pdf.pxml.Ppage;
import com.pxml2pdf.pxml.Pxml;
import com.pxml2pdf.utility.X2pUtility;

public class PageManger {

	public static final Float PAGE_HEIGHT = 780f;
	public static final Float PAGE_WIDTH = 580f;
	public static final Float PAGE_LEFT_OFF = 10f;
	public static final Float PAGE_TOP_OFF = 40f;
	public static final Float PAGE_TOP_MAX = PAGE_HEIGHT + PAGE_TOP_OFF;
	public static final Float LABEL_Y_EX=3f;

	public static boolean canDrawing(float lly, float ury) {
		if (lly < PageSize.A4.getHeight() || ury > 0f)
			return true;
		return false;
	}

	public static boolean canDrawingEx(float lly, float ury) {
		if (lly < PAGE_TOP_MAX && ury > PAGE_TOP_OFF)
			return true;
		return false;
	}

	private List<PageInfo> pageList = new ArrayList<PageInfo>();

	public List<PageInfo> getPageList() {
		return pageList;
	}

	public PageManger(Pxml pxmlObj) {
		if (pxmlObj.getWidth().doubleValue() == 0d) {
			pxmlObj.setWidth(PAGE_WIDTH);
		}
		Float scale_X = PAGE_WIDTH / pxmlObj.getWidth();
		Float addheight = 0f;
		List<pageOff> pageOffList = new ArrayList<pageOff>();
		for (Ppage ppage : pxmlObj.getPpageList()) {
			boolean isOK = false;
			while (!isOK) {
				isOK = true;
				for (BaseNode pnode : ppage.getPnodeList()) {
					if (NodeFactory.XGRID.equals(pnode.getNodeType())||NodeFactory.DIV.equals(pnode.getNodeType())) {
						continue;
					}
					if ((pnode.getHeight() * scale_X) > PAGE_HEIGHT) {
						continue;
					}
					float allTop = (pnode.getTop() + addheight) * scale_X;
					float off = getOff(pageOffList, allTop);
					float allTopaddOff = allTop + off;
					float top = PAGE_HEIGHT - (int) (allTopaddOff % PAGE_HEIGHT) + PAGE_TOP_OFF;
					if ((top - pnode.getHeight() * scale_X) < PAGE_TOP_OFF) {
						pageOffList.add(new pageOff((int) allTop, top - PAGE_TOP_OFF));
						if (pageOffList.size() < 1000) {
							isOK = false;
							break;
						}
					}
				}
			}
			for (BaseNode pnode : ppage.getPnodeList()) {
				float allTop = (pnode.getTop() + addheight) * scale_X;
				allTop += getOff(pageOffList, allTop);
				int top_mod =(int) (allTop % PAGE_HEIGHT);
//				if ((top_mod<LABEL_Y_EX) && LabelNode.class.isInstance(pnode) ){
//					System.out.println("      top_mod:"+top_mod+ "       id:" +pnode.getId() + "       " +pnode.getValue());
//				}
				int pageIndex = (int) (allTop / PAGE_HEIGHT);
				float top = PAGE_HEIGHT - top_mod + PAGE_TOP_OFF;
				//System.out.println("pageIndex:"+pageIndex+"      top_mod:"+top_mod+" top:" + top + "       " +pnode.getValue());
				//System.out.println("allTop:"+allTop+" top:" + top + "       " +pnode.getValue());
				pnode.setUry(top);
				pnode.setScale(scale_X);
				pnode.setLlx(PAGE_LEFT_OFF + pnode.getLeft() * scale_X);
				pnode.setUrx(pnode.getLlx() + pnode.getWidth() * scale_X);
				pnode.setLly(pnode.getUry() - pnode.getHeight() * scale_X);
				pnode.setAlign(X2pUtility.convertAlign(pnode.getTextAlign()));
				getPageInfo(pageIndex).addNode(pnode);
				if (NodeFactory.XGRID.equals(pnode.getNodeType())) {
					float lly = pnode.getLly();
					// System.out.println(" lly:"+lly);
					while (lly < PAGE_TOP_OFF) {
						lly += PAGE_HEIGHT;
						pageIndex++;
						getPageInfo(pageIndex).addNode(pnode);
					}
				}
			}
			addheight += ppage.getHeight();
		}
		//System.out.println(pageOffList.size());
	}

	private float getOff(List<pageOff> pageOffList, float allTop) {
		float off = 0f;
		for (pageOff po : pageOffList) {
			if (po.getTop() <= allTop) {
				off += po.getOff();
			}
		}
		return off;
	}

	public PageInfo getPageInfo(int pageIndex) {
		for (PageInfo pi : pageList) {
			if (pi.getIndex().intValue() == pageIndex) {
				return pi;
			}
		}
		PageInfo pi = new PageInfo();
		pi.setIndex(pageIndex);
		pageList.add(pi);
		return pi;
	}

}

class pageOff {
	private int top;
	private float off;

	public pageOff(int topx, float offx) {
		top = topx;
		off = offx;
	}

	public float getTop() {
		return top;
	}

	public void setTop(int top) {
		this.top = top;
	}

	public float getOff() {
		return off;
	}

	public void setOff(float off) {
		this.off = off;
	}

}
